
#include "delay.h"
#include "printf.h"
#include <stdbool.h>
#include <stdio.h>
#include <stm32f10x.h>

#define p() printf("%d\r\n", __LINE__)
#define g() printf("%d: GPIOA=%#X\r\n", __LINE__, GPIO_ReadInputData(GPIOA))

typedef unsigned char byte;
typedef byte u8;
typedef unsigned short u16;

void GPIOA_enable() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); }

void GPIOA_0_to_2_init() {

    GPIOA_enable();
    GPIO_InitTypeDef def;

    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    def.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &def);

    // VCC
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
    // GND
    GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_RESET);
    // idle A1 = 1
    GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
}

void DHT11_output_config() {

    GPIOA_enable();
    GPIO_InitTypeDef def;

    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Pin = GPIO_Pin_1;
    def.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &def);
}

void DHT11_input_config() {

    GPIOA_enable();
    GPIO_InitTypeDef def;

    def.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    def.GPIO_Pin = GPIO_Pin_1;

    GPIO_Init(GPIOA, &def);
}

void DHT11_write_bit(int b) {
    if (b == 1) {
        GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
    } else {
        GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
    }
}

byte DHT11_read_bit() { return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); }

bool DHT11_start() {

    for (int i = 0; i < 10; i++) {

        DHT11_output_config();
        // g();
        // 空闲状态为高电平
        DHT11_write_bit(1);
        // g();
        delay_ms(10);

        // low
        DHT11_write_bit(0);
        // g();
        // > 18ms
        delay_ms(20);

        DHT11_write_bit(1);

        delay_us(30);

        DHT11_input_config();

        byte response = DHT11_read_bit();

        // g();
        if (response == 0) {
            // delay_us(80);
            // 等待80us的低电平
            while (DHT11_read_bit() == 0)
                ;
            // 等待80us的高电平
            while (DHT11_read_bit() == 1)
                ;
            // p();
            return true;
        }
    }
    return false;
}

bool DHT11_read_data(u16 *humidity, u16 *temperature) {

    *humidity = 0;
    *temperature = 0;
    byte data[5] = {0};

    if (DHT11_start()) {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 8; j++) {
                byte bit = DHT11_read_bit();

                if (bit == 0) {
                    while (DHT11_read_bit() == 0)
                        ;
                    // delay_us(50);
                    bit = DHT11_read_bit();
                    if (bit == 1) {
                        delay_us(30);
                        if (DHT11_read_bit() == 1) {

                            // delay_us(40);
                            data[i] = 1 << (7 - j);
                            while (DHT11_read_bit() == 1)
                                ;
                        }
                        // set data
                        //
                    }
                }
            }
        }
        // 数据校验
        byte check = data[0] + data[1] + data[2] + data[3];
        if (check == data[4]) {
            *humidity = data[0];
            *temperature = data[2];
        }
        return true;
    }
    return false;
}

int main() {

    printf_init(9600);
    delay_init();

    GPIOA_0_to_2_init();
    u16 humidity = 0, temperature = 0;
    while (true) {

        delay_s(10);
        printf("main running\r\n");

        if (DHT11_read_data(&humidity, &temperature)) {
            printf("humidity = %d,temperature = %d\r\n", humidity, temperature);
        }

        printf("GPIOA = %#X\r\n", GPIO_ReadInputData(GPIOA));

        delay_s(2);
    }

    return 0;
}
